/****************************************************************************
* Copyright (c) 2014 Shijie. Dreamware(R) Inc. JuneStone Entertainment
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*****************************************************************************/

#ifndef __AUTO_REF_H__
#define __AUTO_REF_H__

template<typename T>
class autoref
{
public:
	autoref(T *t = NULL)
	{
		m_p = t;
		if (t != NULL) { m_p->grab(); }
	}

	~autoref()
	{
		if (m_p != NULL) { m_p->drop(); }
	}
 
	autoref(const T& t)
	{
		m_p = t;
		if (m_p != NULL) { m_p->grab(); }
	}

	autoref &operator=(T *ptr)
	{
		if (ptr != NULL) { ptr->grab(); }
		if (m_p != NULL) { m_p->drop(); }
		m_p = ptr;
		return (*this);
	}

	autoref& operator=(const autoref &ptr)
	{
		return (*this) = ptr.m_p;
	}

	T* get() const
	{
		return m_p;
	}

	T* operator->() const { return m_p; }		//x->member

	T &operator*() const { return *m_p; }		//*x, (*x).member

	operator T*() const { return m_p; }		    //T* y = x;

	operator bool() const { return m_p != NULL; }	//if(x) {/*x is not NULL*/}

	bool operator==(const autoref &ptr) { return m_p == ptr.m_p; }

	bool operator==(const T *ptr) { return m_p == ptr; }
	
private:
	T* m_p;
};

#endif